﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetSMA.Model
{
    public class Prey : ItemMove
    {

        private List<Food> m_food = new List<Food>();

        private bool m_has_eaten = false;
        private bool m_has_bred = false;
 
       

        public Prey(Element par_position_now, float par_growth, string par_name)
            : base(par_position_now, par_growth, par_name)
        {
            // prey don't need a lot of food
            m_starvation_max = 45;
        }

        public override void Live()
        {
            base.Live();
            m_food = new List<Food>();
            DetectionFood();
            SortItemMoveViewed();

            if (m_food.Count > 0)
            {                    
                m_decision.UpdateList("_eating", 1, true);
            }
            else
            {
                // starvation all time
                m_decision.UpdateList("_eating", 1, false);
            }

            if (m_item_friends.Count > 0 && m_cpt_child < m_cpt_child_max && m_growth == m_growth_max)
            {
                // desire of breeding
                m_want_breed = true;
                m_decision.UpdateList("_breeding", 1, true);

            }

            if (m_item_foes.Count > 0)
            {               
                m_decision.UpdateList("_escaping", 10, true);
                m_decision.UpdateList("_eating", 1, false);
            }
          
            m_type_decision = m_decision.ChoseDecision();           

            switch (m_type_decision)
            {
                case "_breeding":
                    CaseBreeding();
                    break;

                case "_eating":
                    CaseEating();
                    break;

                case "_escaping":
                    CaseEscaping();
                    break;

                case "_nothing":
                    MoveRandom();
                    m_decision.ResetState();
                    base.Live();
                    break;
            }


            if(m_elements_visible.Count==0)
            {
                MoveRandom();
                base.Live();
            }
            
        }

        public bool DetectFoes()
        {
            foreach (ItemMove loc_item in m_position_now.Occupants)
            {
                if (loc_item is Predator)
                    return true;
            }
            return false;
        }

        public void DetectionFood()
        {
            foreach (Element loc_elem in m_elements_visible)
            {
                if (loc_elem.Food != null)
                    m_food.Add(loc_elem.Food);
            }
        }
        public void CaseBreeding()
        {
            if (m_has_bred)
            {
                if (m_growth == m_growth_max && m_item_friends[0].WantBreed == true)
                {
                    m_cpt_child++;
                    m_children.Add(new Prey(m_position_now, 1, m_name + m_cpt_child));
                }
                
                m_decision.ResetValue("_breeding", 0);
                m_has_bred = false;
                m_want_breed = false;
            }
            else
            {
                Breed();
            }

            m_decision.ResetState();
        }
        public void Breed()
        {
            if (InListNeighboors(m_item_friends[0].PositionNow) || m_position_now == m_item_friends[0].PositionNow)
                m_has_bred = true;

            if (m_position_now != m_item_friends[0].PositionNow)
                Aetoile(m_item_friends[0].PositionNow);              
        }

        public void CaseEscaping()
        {
            if (DetectFoes())
            {
                Killed = true;
                m_position_now.Occupants.Remove(this);
            }
            else
                Escape();

            m_decision.ResetValue("_escaping", 0);
            m_decision.ResetState();
        }
        public void Escape()
        {
            if (InListVisible(m_item_foes[0].PositionNow))
            {
                this.SetDirectionOpposite();
                DeterminedVisiblesElements();
                SortItemMoveViewed();
            }
            Aetoile(ChoixCible(m_item_foes[0]));           
        }
        public void CaseEating()
        {
            if (m_has_eaten)
            {
                PositionNow.Food = null;
                m_decision.ResetValue("_eating", 0);
                m_has_eaten = false;
                m_starvation = 0;
            }
            else
                Eat();

            m_decision.ResetState();
        }
        public void Eat()
        {
            if (InListNeighboors(m_food[0].Position) ||m_position_now.Food == m_food[0])
                m_has_eaten = true;

            if (m_position_now.Food != m_food[0])
                Aetoile(m_food[0].Position);                
           
        }

        public void SetDirectionOpposite()
        {
            if (m_name_direction == "_south")
                m_name_direction = "_north";
            else if (m_name_direction == "_south_west")
                m_name_direction = "_north_east";
            else if (m_name_direction == "_west")
                m_name_direction = "_east";
            else if (m_name_direction == "_north_west")
                m_name_direction = "_south_east";
            else if (m_name_direction == "_north")
                m_name_direction = "_south";
            else if (m_name_direction == "_north_east")
                m_name_direction = "_south_west";
            else if (m_name_direction == "_east")
                m_name_direction = "_west";
            else if (m_name_direction == "_south_east")
                m_name_direction = "_north_west";
        }
        
        private Element ChoixCible(ItemMove par_item)
        {
            Element loc_tmp = par_item.PositionNow;
            foreach (Element loc_elem in m_elements_visible)
            {
                if (CalculDistance(par_item.PositionNow, loc_tmp) < CalculDistance(par_item.PositionNow, loc_elem))
                    loc_tmp = loc_elem;
            }
            return loc_tmp;
        }

        private double CalculDistance(Element par_elem1, Element par_elem2)
        {
            return Math.Sqrt(Math.Pow(par_elem1.I - par_elem2.I, 2) + Math.Pow(par_elem1.J - par_elem2.J, 2));
        }
        
        public bool Perception()
        {
            foreach(Element loc_elem in m_perception)
            {
                if(loc_elem.Occupants.Count != 0)
                    return true;
                }
            return false;
            }

        public void SortItemMoveViewed()
        {

            foreach (ItemMove loc_item in m_item_viewed)
            {
                if (loc_item != this)
                {
                    if (TestPrey(loc_item))
                        m_item_friends.Add(loc_item);
                    else
                        m_item_foes.Add(loc_item);
                }
            }  
        }

        private bool TestPrey(Object o)
        {
            if (o is Prey)
                return true;
            return false;
        }

       


    }
}
